#include "OS.h"
#include "OSCon.h"
#include "WavFile.h"

using namespace host;

WavFile::WavFile()
{
    m_u32DataLen = 0;
    m_u32DataPos = 0;
}

bool WavFile::Open(const char* i_pPath)
{

    FILE* fOut = NULL;
    fOut = fopen(i_pPath, "rb");
    if (fOut == NULL)
    {
        OSCon::PrintR("Open file<%s> failed\n", i_pPath);
        return false;
    }

    fread(&m_WaveHdr, 1, sizeof(Wave_t), fOut);

    m_pFile = fOut;
    m_u32DataLen = m_WaveHdr.DataChunk_t.u32SubChunkSize;
    m_u32DataPos = sizeof(Wave_t);

    return true;
}

bool WavFile::Create(const char* i_pPath, unsigned int i_u32SampleRate, unsigned int i_u32Channel, unsigned int i_u32BitsPerSample)
{
    Wave_t wave = {
        {
            'F'<<24|'F'<<16|'I'<<8|'R', /*u32ChunkID*/
             44,                        /*u32ChunkSize*/
           'E'<<24|'V'<<16|'A'<<8|'W', /*u32Format*/
        },
        {
            ' '<<24|'t'<<16|'m'<<8|'f',
            16,
            1,
            (unsigned short)i_u32Channel,
            i_u32SampleRate,
            i_u32SampleRate* i_u32Channel* i_u32BitsPerSample / 8,
            (unsigned short)(i_u32Channel* i_u32BitsPerSample / 8),
            (unsigned short)i_u32BitsPerSample,
        },
        {
            'a'<<24|'t'<<16|'a'<<8|'d',
            0,
        },
    };

    FILE *fOut = NULL;
    fOut = fopen(i_pPath, "wb");
    if (fOut == NULL)
    {
        OSCon::PrintR("Open file<%s> failed\n", i_pPath);
        return false;
    }

    m_pFile = fOut;
    m_u32DataLen = 0;
    m_u32DataPos = sizeof(Wave_t);
    memcpy(&m_WaveHdr, &wave, sizeof(Wave_t));

    // RIFF chunk
    ::fwrite(&wave, 1, sizeof(Wave_t), fOut);

    return true;
}

int WavFile::Write(unsigned char* i_pBuffer, unsigned int i_u32Len)
{
    if (m_pFile == NULL)
    {
        OSCon::PrintR("WavFile Write file failed, m_pFile is NULL\n");
        return -1;
    }

    auto retval = fwrite(i_pBuffer, 1, i_u32Len, m_pFile);
    if (retval != i_u32Len)
    {
        OSCon::PrintR("WavFile Write file failed, retval(%d) i_u32Len(%d)\n", retval, i_u32Len);
    }
    m_u32DataLen += i_u32Len;

    return (int)retval;
}

int WavFile::Read(unsigned char* o_pBuffer, unsigned int i_u32Len)
{
    if (m_pFile == NULL)
    {
        OSCon::PrintR("WavFile Write file failed, m_pFile is NULL\n");
        return -1;
    }

    auto retval = fread(o_pBuffer, 1, i_u32Len, m_pFile);
    if (retval != i_u32Len)
    {
        OSCon::PrintR("WavFile Read file failed, retval(%d) i_u32Len(%d)\n", retval, i_u32Len);
    }

    return (int)retval;
}

bool WavFile::Refresh()
{
    m_WaveHdr.ChunkHeader_t.u32ChunkSize = m_u32DataLen + sizeof(Wave_t) - 8;
    m_WaveHdr.DataChunk_t.u32SubChunkSize = m_u32DataLen;
    fseek(m_pFile, 0, SEEK_SET);
    fwrite(&m_WaveHdr, 1, sizeof(Wave_t), m_pFile);
    fseek(m_pFile, m_u32DataPos, SEEK_SET);

    return true;
}

void WavFile::Close()
{
    Refresh();

    fclose(m_pFile);
}
